using NICWebApi.Extensions.Http.Models;
using NICWebApi.Extensions.Http.Options;

using System.Text;

/// <summary>
/// HTTP上下文工具类
/// </summary>
public class HttpContextUtils : IHttpContextUtils
{
    private readonly IOptions<HttpOptions> _options;
    private readonly IHttpContextAccessor _httpContextAccessor;

    private static readonly HashSet<string> _botKeywords = new(StringComparer.OrdinalIgnoreCase)
    {
        "bot", "crawler", "spider", "slurp", "search", "mediapartners", "nagios", "monitoring",
        "whatsapp", "facebook", "twitter", "linkedin", "google", "bing", "yandex", "baidu"
    };

    /// <summary>
    /// 初始化HTTP上下文工具类
    /// </summary>
    /// <param name="options">HTTP选项</param>
    /// <param name="httpContextAccessor">HTTP上下文访问器</param>
    public HttpContextUtils(IOptions<HttpOptions> options, IHttpContextAccessor httpContextAccessor)
    {
        _options = options ?? throw new ArgumentNullException(nameof(options));
        _httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
    }

    /// <summary>
    /// 获取当前HTTP上下文
    /// </summary>
    private HttpContext CurrentContext => _httpContextAccessor.HttpContext ?? throw new InvalidOperationException("当前没有活动的HTTP上下文");

    /// <summary>
    /// 获取客户端IP地址
    /// </summary>
    /// <returns>IP地址和提供者</returns>
    public (string IpAddress, string Provider) GetClientIpAddress()
    {
        var options = _options.Value;
        string? ipAddress = null;
        string provider = "RemoteIpAddress";

        // 尝试从自定义头获取
        if (!string.IsNullOrEmpty(options.IpHeaders.CustomIpHeader))
        {
            ipAddress = GetIpFromHeaderValue(CurrentContext.Request.Headers[options.IpHeaders.CustomIpHeader].ToString(), options);
            if (!string.IsNullOrEmpty(ipAddress))
            {
                provider = options.IpHeaders.CustomIpHeader;
                return (ipAddress, provider);
            }
        }

        // 尝试从X-Forwarded-For获取
        if (options.IpHeaders.UseXForwardedFor)
        {
            ipAddress = GetIpFromHeaderValue(CurrentContext.Request.Headers["X-Forwarded-For"].ToString(), options);
            if (!string.IsNullOrEmpty(ipAddress))
            {
                provider = "X-Forwarded-For";
                return (ipAddress, provider);
            }
        }

        // 尝试从X-Real-IP获取
        if (options.IpHeaders.UseXRealIp)
        {
            ipAddress = GetIpFromHeaderValue(CurrentContext.Request.Headers["X-Real-IP"].ToString(), options);
            if (!string.IsNullOrEmpty(ipAddress))
            {
                provider = "X-Real-IP";
                return (ipAddress, provider);
            }
        }

        // 使用RemoteIpAddress
        ipAddress = CurrentContext.Connection.RemoteIpAddress?.ToString();

        // 将IPv6 loopback转换为IPv4格式
        if (ipAddress == "::1")
        {
            ipAddress = "127.0.0.1";
        }

        return (ipAddress ?? "0.0.0.0", provider);
    }

    /// <summary>
    /// 从请求头值中获取IP地址
    /// </summary>
    private string? GetIpFromHeaderValue(string headerValue, HttpOptions options)
    {
        if (string.IsNullOrWhiteSpace(headerValue))
        {
            return null;
        }

        // 分割多个IP地址
        var ips = headerValue.Split(new[] { options.IpHeaders.IpSeparator }, StringSplitOptions.RemoveEmptyEntries)
            .Select(ip => ip.Trim())
            .Where(IsValidIpAddress)
            .ToList();

        return ips.FirstOrDefault();
    }

    /// <summary>
    /// 验证IP地址格式
    /// </summary>
    private bool IsValidIpAddress(string ipAddress)
    {
        return IPAddress.TryParse(ipAddress, out _);
    }

    /// <summary>
    /// 获取Web请求信息
    /// </summary>
    /// <param name="httpContext">HTTP上下文</param>
    /// <param name="includeHeaders">是否包含请求头</param>
    /// <returns>HTTP上下文信息</returns>
    public HttpContextInfo GetRequestInfo(bool includeHeaders = true)
    {
        var result = new HttpContextInfo
        {
            Host = CurrentContext.Request.Host.Value,
            Path = CurrentContext.Request.Path.Value,
            Method = CurrentContext.Request.Method,
            QueryString = CurrentContext.Request.QueryString.Value,
            Protocol = CurrentContext.Request.Protocol
        };

        // 获取客户端IP
        var (ipAddress, provider) = GetClientIpAddress();
        result.ClientIpAddress = ipAddress;
        result.IpAddressProvider = provider;

        // 获取Controller和Action信息
        var endpoint = CurrentContext.GetEndpoint();
        if (endpoint != null)
        {
            var controllerActionDescriptor = endpoint.Metadata.GetMetadata<ControllerActionDescriptor>();
            if (controllerActionDescriptor != null)
            {
                result.ControllerName = controllerActionDescriptor.ControllerName;
                result.ActionName = controllerActionDescriptor.ActionName;
            }
        }

        // 获取路由数据
        var routeData = CurrentContext.GetRouteData();
        if (routeData != null)
        {
            foreach (var routeValue in routeData.Values)
            {
                result.RouteData.Add(routeValue.Key, routeValue.Value?.ToString());
            }
        }

        // 获取授权信息
        if (CurrentContext.User?.Identity?.IsAuthenticated == true)
        {
            result.UserId = CurrentContext.User.FindFirst("sub")?.Value
                ?? CurrentContext.User.FindFirst("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier")?.Value;

            result.Username = CurrentContext.User.FindFirst("name")?.Value
                ?? CurrentContext.User.Identity.Name;

            var roles = CurrentContext.User.FindAll("role")
                .Select(c => c.Value)
                .ToList();

            if (roles.Any())
            {
                result.UserRoles = string.Join(",", roles);
            }
        }

        // 获取Referer
        result.Referer = CurrentContext.Request.Headers["Referer"].ToString();

        // 获取Session ID
        // result.SessionId = CurrentContext?.Session != null ? CurrentContext?.Session?.Id : "";

        // 获取请求头
        if (includeHeaders)
        {
            foreach (var header in CurrentContext.Request.Headers)
            {
                // 隐藏敏感信息
                var value = header.Key.ToLower() switch
                {
                    "authorization" => "******",
                    "cookie" => "******",
                    _ => header.Value.ToString()
                };

                result.RequestHeaders.Add(header.Key, value);
            }
        }

        // 获取状态码
        if (CurrentContext.Response.HasStarted)
        {
            result.StatusCode = CurrentContext.Response.StatusCode;
        }

        return result;
    }

    /// <summary>
    /// 解析用户代理信息
    /// </summary>
    /// <param name="userAgent">用户代理字符串</param>
    /// <returns>用户代理信息</returns>
    public UserAgentInfo ParseUserAgent(string userAgent)
    {
        if (string.IsNullOrEmpty(userAgent))
        {
            return new UserAgentInfo { RawValue = userAgent };
        }

        var result = new UserAgentInfo
        {
            RawValue = userAgent
        };

        // 检测是否为爬虫
        if (IsBot(userAgent, out string botName))
        {
            result.IsBot = true;
            result.BotName = botName;
            return result;
        }

        // 解析浏览器信息
        ParseBrowserInfo(userAgent, result);

        // 解析操作系统信息
        ParseOSInfo(userAgent, result);

        // 解析设备信息
        ParseDeviceInfo(userAgent, result);

        return result;
    }

    /// <summary>
    /// 检测是否为爬虫
    /// </summary>
    private bool IsBot(string userAgent, out string botName)
    {
        botName = string.Empty;
        foreach (var keyword in _botKeywords)
        {
            if (userAgent.Contains(keyword, StringComparison.OrdinalIgnoreCase))
            {
                botName = keyword;
                return true;
            }
        }
        return false;
    }

    /// <summary>
    /// 解析浏览器信息
    /// </summary>
    private void ParseBrowserInfo(string userAgent, UserAgentInfo info)
    {
        if (userAgent.Contains("Chrome", StringComparison.OrdinalIgnoreCase))
        {
            info.Browser = "Chrome";
        }
        else if (userAgent.Contains("Firefox", StringComparison.OrdinalIgnoreCase))
        {
            info.Browser = "Firefox";
        }
        else if (userAgent.Contains("Safari", StringComparison.OrdinalIgnoreCase))
        {
            info.Browser = "Safari";
        }
        else if (userAgent.Contains("Edge", StringComparison.OrdinalIgnoreCase))
        {
            info.Browser = "Edge";
        }
        else if (userAgent.Contains("MSIE", StringComparison.OrdinalIgnoreCase) || userAgent.Contains("Trident", StringComparison.OrdinalIgnoreCase))
        {
            info.Browser = "Internet Explorer";
        }
        else
        {
            info.Browser = "Unknown";
        }
    }

    /// <summary>
    /// 解析操作系统信息
    /// </summary>
    private void ParseOSInfo(string userAgent, UserAgentInfo info)
    {
        if (userAgent.Contains("Windows", StringComparison.OrdinalIgnoreCase))
        {
            info.OperatingSystem = "Windows";
        }
        else if (userAgent.Contains("Mac OS X", StringComparison.OrdinalIgnoreCase))
        {
            info.OperatingSystem = "macOS";
        }
        else if (userAgent.Contains("Linux", StringComparison.OrdinalIgnoreCase))
        {
            info.OperatingSystem = "Linux";
        }
        else if (userAgent.Contains("Android", StringComparison.OrdinalIgnoreCase))
        {
            info.OperatingSystem = "Android";
        }
        else if (userAgent.Contains("iOS", StringComparison.OrdinalIgnoreCase) || userAgent.Contains("iPhone", StringComparison.OrdinalIgnoreCase) || userAgent.Contains("iPad", StringComparison.OrdinalIgnoreCase))
        {
            info.OperatingSystem = "iOS";
        }
        else
        {
            info.OperatingSystem = "Unknown";
        }
    }

    /// <summary>
    /// 解析设备信息
    /// </summary>
    private void ParseDeviceInfo(string userAgent, UserAgentInfo info)
    {
        if (userAgent.Contains("Mobile", StringComparison.OrdinalIgnoreCase) || userAgent.Contains("Android", StringComparison.OrdinalIgnoreCase) || userAgent.Contains("iPhone", StringComparison.OrdinalIgnoreCase))
        {
            info.DeviceType = "Mobile";
            info.IsMobile = true;
        }
        else if (userAgent.Contains("Tablet", StringComparison.OrdinalIgnoreCase) || userAgent.Contains("iPad", StringComparison.OrdinalIgnoreCase))
        {
            info.DeviceType = "Tablet";
            info.IsTablet = true;
        }
        else
        {
            info.DeviceType = "Desktop";
        }
    }

    /// <summary>
    /// 获取客户端浏览器信息
    /// </summary>
    /// <returns>浏览器信息</returns>
    public string GetUserAgent()
    {
        return CurrentContext.Request.Headers["User-Agent"].ToString();
    }

    /// <summary>
    /// 获取当前请求的URL
    /// </summary>
    /// <param name="includeQueryString">是否包含查询字符串</param>
    /// <returns>完整URL</returns>
    public string GetRequestUrl(bool includeQueryString = true)
    {
        var request = CurrentContext.Request;
        var url = $"{request.Scheme}://{request.Host}{request.Path}";
        return includeQueryString ? $"{url}{request.QueryString}" : url;
    }

    /// <summary>
    /// 获取请求头值
    /// </summary>
    /// <param name="headerName">请求头名称</param>
    /// <returns>请求头值</returns>
    public string GetHeaderValue(string headerName)
    {
        return CurrentContext.Request.Headers[headerName].ToString();
    }

    /// <summary>
    /// 获取请求头集合
    /// </summary>
    /// <param name="headerNames">请求头名称列表</param>
    /// <returns>请求头集合</returns>
    public IDictionary<string, string> GetHeaderValues(IEnumerable<string> headerNames)
    {
        var result = new Dictionary<string, string>();
        foreach (var headerName in headerNames)
        {
            result[headerName] = GetHeaderValue(headerName);
        }
        return result;
    }

    /// <summary>
    /// 获取请求来源URL
    /// </summary>
    /// <returns>来源URL</returns>
    public string GetReferrer()
    {
        return CurrentContext.Request.Headers["Referer"].ToString();
    }

    /// <summary>
    /// 获取请求的路由值
    /// </summary>
    /// <param name="routeValueKey">路由值键</param>
    /// <returns>路由值</returns>
    public string GetRouteValue(string routeValueKey)
    {
        return CurrentContext.GetRouteValue(routeValueKey)?.ToString() ?? string.Empty;
    }

    /// <summary>
    /// 判断请求是否为AJAX请求
    /// </summary>
    /// <returns>是否为AJAX请求</returns>
    public bool IsAjaxRequest()
    {
        return CurrentContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest";
    }

    /// <summary>
    /// 判断请求是否为移动设备
    /// </summary>
    /// <returns>是否为移动设备</returns>
    public bool IsMobileDevice()
    {
        var userAgent = GetUserAgent();
        var userAgentInfo = ParseUserAgent(userAgent);
        return userAgentInfo.IsMobile;
    }

    /// <summary>
    /// 获取请求的内容类型
    /// </summary>
    /// <returns>内容类型</returns>
    public string GetContentType()
    {
        return CurrentContext.Request.ContentType ?? string.Empty;
    }

    /// <summary>
    /// 登录Swagger
    /// </summary>
    /// <param name="accessToken"></param>
    public void SignInToSwagger(string accessToken)
    {
        CurrentContext.Response.Headers["access-token"] = accessToken;
    }

    /// <summary>
    /// 登出Swagger
    /// </summary>
    public void SignOutToSwagger()
    {
        CurrentContext.Response.Headers["access-token"] = "invalid_token";
    }

    /// <summary>
    /// 获取 Action 特性
    /// </summary>
    /// <typeparam name="TAttribute"></typeparam>
    /// <returns></returns>
    public TAttribute GetMetadata<TAttribute>() where TAttribute : class
    {
        return CurrentContext.GetEndpoint()?.Metadata?.GetMetadata<TAttribute>();
    }

    /// <summary>
    /// 获取控制器方法描述
    /// </summary>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public ControllerActionDescriptor GetControllerActionDescriptor()
    {
        return (CurrentContext.GetEndpoint()?.Metadata?.FirstOrDefault(u => u is ControllerActionDescriptor)) as ControllerActionDescriptor; ;
    }

    /// <summary>
    /// 获取路由数据
    /// </summary>
    /// <returns></returns>
    public RouteData GetRouteData()
    {
        return CurrentContext.GetEndpoint()?.Metadata?.FirstOrDefault(u => u is RouteData) as RouteData;
    }

    /// <summary>
    /// 设置响应头中的Token信息
    /// </summary>
    /// <param name="accessToken"></param>
    /// <param name="refreshToken"></param>
    /// <exception cref="NotImplementedException"></exception>
    public void SetTokensOfResponseHeaders(string accessToken, string refreshToken = null)
    {
        CurrentContext.Response.Headers["access-token"] = accessToken;
        if (!string.IsNullOrWhiteSpace(refreshToken))
        {
            CurrentContext.Response.Headers["x-access-token"] = refreshToken;
        }
    }

    /// <summary>
    /// 读取请求体内容
    /// </summary>
    /// <returns></returns>
    public async Task<string> ReadBodyContentAsync()
    {
        CurrentContext.Request.Body.Seek(0, SeekOrigin.Begin);

        using var reader = new StreamReader(CurrentContext.Request.Body, Encoding.UTF8, true, 1024, true);
        var body = await reader.ReadToEndAsync();

        CurrentContext.Request.Body.Seek(0, SeekOrigin.Begin);
        return body;
    }
}